package com.sunnay.util;

import com.sunnay.callback.Function;
import com.sunnay.enums.GbCodeEnum;
import com.sunnay.exception.DataException;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class RedisLockExecutor {

    @Autowired
    RedissonClient redissonClient;


    public <T>T execute(Function<Object, T> function, String lockName){
        return execute(function, lockName,null);
    }

    public <T>T execute(Function<Object, T> function, String lockName,Function<Object, T> errFunction){
        //加锁
        RLock lock = redissonClient.getLock(lockName);
        return lockAndUnlock(lock, function,errFunction);
    }


    public <T>T lockAndUnlock(RLock lock, Function<Object, T> function, Function<Object, T> errFunction) {
        try {
            boolean b = lock.tryLock(100, 30000, TimeUnit.MILLISECONDS);
            if(b){
                //业务逻辑 ====START
                return function.callback(null);
                //业务逻辑 ====END
            }else{
                if (errFunction != null) {
                    errFunction.callback(null);
                }else{
                    throw new DataException(GbCodeEnum.SYSTEM_NETWORK_ERROR);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        return null;
    }
}
